﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufArrangementAreaContent.h"
#include "GnufImpl.h"

namespace gnuf {
    class DynamicPanel;

    namespace impl { class GNUF_IMPL_CLASS(DynamicZone); }
    class GNUF_BASE_EXPORT DynamicZone : public ArrangementAreaContent
    {
        DEFINE_CAST_DERIVED(DynamicZone, ArrangementAreaContent)
        CANNOT_COPY_OR_ASSIGN(DynamicZone)
        GNUF_IMPL_USE(DynamicZone);
        
    public:
        DynamicZone();
        virtual ~DynamicZone();
        static DynamicZone * get();

        ///\brief Refresh the Dynamic Panel at the index.
        ///\param index: the index of the Dynamic Panel.
        ///\return Return the Dynamic Panel. Return nullptr, if the index isn't valid.
        DynamicPanel * refreshDynamicPanelAt(int index);
        
        ///\brief Refresh the Dynamic Panel by the key.
        ///\param key: the key of the Dynamic Panel.
        ///\return Return the Dynamic Panel. if the key isn't valid.
        DynamicPanel * refreshDynamicPanelBy(const std::wstring & key);
        
        ///\return Return the Dynamic Panel at the index. Return nullptr, if the index isn't valid.
        ///\param index: the index of the Dynamic Panel.
        DynamicPanel * getDynamicPanelAt(int index);
        
        ///\return Return the Dynamic Panel by the key. Return nullptr, if the key isn't valid.
        ///\param key: the key of the Dynamic Panel.
        DynamicPanel * getDynamicPanelBy(const std::wstring & key);
        
        ///\brief Clear the Dynamic Panel at the index.
        ///\param index: the index of the Dynamic Panel.
        void clearDynamicPanelAt(int index);
        
        ///\brief Clear the Dynamic Panel by the key.
        ///\param key: the key of the Dynamic Panel.
        void clearDynamicPanelBy(const std::wstring & key);
        
        ///\brief Clear all of the Dynamic Panel(s).
        void clearAllDynamicPanel();
        
        ///\brief Refresh respectively each Dynamic Panel's status.
        void refreshStatus();
        
        ///\return Return true if the unique key is a Dynamic Panel.
        bool isDynamicPanel(const gcmp::UniqueString * uniqueKey) const;
        
        ///\return Return all of the Dynamic Panel(s).
        std::vector<DynamicPanel* > rawDynamicPanel();
        
        ///\brief Show or hide the Dynamic Zone, as well as all of the Dynamic Panel(s).
        /// The Dynamic Zone is special, it doesn't work to show or hide in the normal way:
        ///
        ///   gnuf::DynamicZone     * pDyZone = DynamicZone::get();
        ///   gnuf::ArrangementArea * pArea   = pDyZone->arrangementArea();
        ///   pArea->setExpectedVisibility(false);
        ///   pArea->submit();
        ///
        /// because:
        ///
        /// - the Arrangement Area of the Dynamic Zone is virtual, but not practical. 
        ///   The visibility of a virtual Arrangement Area is determined by its children.
        ///   That is, show if any child is visible, and hide if none is visible.
        ///
        /// - The logic might go wrong, if modify directly Expected Visibility of each
        ///   child Arrangement Area.
        ///
        ///\param visible: show if true, hide if false.
        void setVisible(bool visible);
        
        ///\return Return ture if visible. Otherwise, return false.
        bool isVisible() const;

    protected:
        // Inherits from ArrangementAreaContent...
        virtual QWidget * qtWidget() override;
        virtual void onPostGeometryChanged() override {}
        virtual void onPostVisibilityChanged() override {}
        virtual void onPostConnectedWithArrangementArea() override;
        virtual void onPreDisconnectedFromArrangementArea() override;
        virtual bool onIsBlank() const;
    private:
        DynamicPanel * clearDynamicPanel(const int, const bool);
        int indexOfDynamicPanel(const std::wstring&);
        std::list< gcmp::OwnerPtr< DynamicPanel > > m_dynamicPanels;

    };
}
